﻿/*
 * Copyright (c) 2025 HiEasyX
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * \file ShowOff.cpp
 * \brief The show off example
 */

#include <graphics.h>

#include <include/hex.h>
#include <include/impl/EasyX/hex_impl_easyx.h>

#include <format>
#include <array>

int main() {
	initgraph(1920, 1080);

	BeginBatchDraw();

	HX::EnableEasyXWindowEnhance();
	HX::HXInitForEasyX();
	if (!HX::Wined()) {
		printf("HX error : %s!", HX::GetLastError().c_str());

		exit(-1);
	}

	IMAGE dogImage;
	loadimage(&dogImage, HXStr("./assets/logo.png"));

	HX::WindowProfile windowProfile;
	windowProfile.Size     = {1020, 1080};
	windowProfile.Position = {617, 176};

	std::array<std::array<float, 2>, 4> Vertexes = {
		std::array<float, 2>{0.0 + 1.0, 0.0 + 1.0}, std::array<float, 2>{1.0 + 1.0, 0.0 + 1.0},
		std::array<float, 2>{1.0 + 1.0, 1.0 + 1.0}, std::array<float, 2>{0.0 + 1.0, 1.0 + 1.0}
	};

	HX::SetBuffer(HX::GetHXBuffer(GetWorkingImage()));

	setbkcolor(RGB(0, 129, 129));
	HX::TextInputProfile textInputProfile;
	textInputProfile.Size = { 400, 100 };
	textInputProfile.Text = HXStr(R"(这是一个文本输入框。)");

	HX::DropdownProfile DropdownProfile;
	DropdownProfile.Items = {HX::Item{HXStr("苹果")}, HX::Item{HXStr("香蕉")}, HX::Item{HXStr("葡萄")}, HX::Item{HXStr("橘子")},
					  HX::Item{HXStr("车厘子")}};

	while (true) {
		cleardevice();

		time_t start = clock();

		HX::HXBegin();

		// Begin to process the message
		ExMessage message{};
		while (peekmessage(&message)) {
			HX::PushMessage(HX::GetHXMessage(&message));
		}

		HX::Window(HXStr("控件展示"), windowProfile);

		static HX::ScrollerProfile windowScroller;

		windowScroller.Size      = {1000, 1080};
		windowScroller.ViewSpace = {1200, 1500};
		HX::BeginScroller(windowScroller);

		HX::TextInput(textInputProfile);
		HX::Dropdown(DropdownProfile);

		HX::TextProfile warningText;
		warningText.Font.Family = HXStr("SongTi");
		warningText.Color       = HXColor{255, 0, 0, 255};
		warningText.Height      = 18;
		HX::Text(HXStr("HX::BeginSameLine() 对下拉菜单（Dropdown）控件不起作用！"), warningText);
		HX::EndSameLine();

		HX::BeginSameLine(); {
			static HX::ScrollerProfile imageViewerScroller;
			imageViewerScroller.ViewSpace      = {dogImage.getwidth(), dogImage.getheight()};
			imageViewerScroller.Size           = {100, 100};
			HX::BeginScroller(imageViewerScroller);
			HX::Image(HX::GetHXBuffer(&dogImage));
			HX::EndScroller(imageViewerScroller);
		} {
			static HX::ScrollerProfile imageViewerScroller;
			imageViewerScroller.ViewSpace      = {dogImage.getwidth(), dogImage.getheight()};
			imageViewerScroller.Size           = {100, 100};
			imageViewerScroller.HorizontalVPer = 0.45;
			imageViewerScroller.VerticalVPer   = 0.45;
			HX::BeginScroller(imageViewerScroller);
			HX::Image(HX::GetHXBuffer(&dogImage));
			HX::EndScroller(imageViewerScroller);
		} {
			static HX::ScrollerProfile imageViewerScroller;
			imageViewerScroller.ViewSpace      = {dogImage.getwidth(), dogImage.getheight()};
			imageViewerScroller.Size           = {100, 100};
			HX::BeginScroller(imageViewerScroller);
			HX::Image(HX::GetHXBuffer(&dogImage));
			HX::EndScroller(imageViewerScroller);
		} {
			static HX::ScrollerProfile imageViewerScroller;
			imageViewerScroller.ViewSpace      = {dogImage.getwidth(), dogImage.getheight()};
			imageViewerScroller.Size           = {100, 100};
			imageViewerScroller.HorizontalVPer = 0.45;
			imageViewerScroller.VerticalVPer   = 0.45;
			HX::BeginScroller(imageViewerScroller);
			HX::Image(HX::GetHXBuffer(&dogImage));
			HX::EndScroller(imageViewerScroller);
		}

		HX::EndSameLine();

		HX::Text(std::format(HXStr("窗口大小 : {}x{}"), windowProfile.Size.X, windowProfile.Size.Y));
		HX::Text(std::format(HXStr("窗口位置 : ({},{})"), windowProfile.Position.X, windowProfile.Position.Y));

		static HX::CheckboxProfile checkboxProfile;
		HX::BeginSameLine();
		if (HX::Checkbox(HXStr("我是单选框"), checkboxProfile)) {
			HX::Text(HXStr("你选中了单选框！"));
		} else {
			HX::Text(HXStr("单选框期待你的选中..."));
		}
		HX::Text(HXStr("我不想被自动对齐"), false);
		HX::TextProfile testTextProfile;
		testTextProfile.Color  = HXColor{235, 205, 215, 255};
		testTextProfile.Height = 14;
		HX::Text(HXStr("我也不想被自动对齐，但是我长得更花"), testTextProfile, false);
		HX::EndSameLine(); {
			static HX::ScrollerProfile Profile;
			Profile.Size      = {300, 100};
			Profile.ViewSpace = {7000, 2000};
			HX::BeginScroller(Profile);
			static HX::ButtonProfile p[30][30];
			for (auto j = 0; j < 30; ++j) {
				HX::BeginSameLine();
				for (auto i = 0; i < 30; ++i) {
					HX::Button(std::format("Test Scroller {}, {}", i, j), p[i][j]);
				}
				HX::EndSameLine();
			}
			HX::EndScroller(Profile);
		} {
			static HX::CheckboxGroupProfile profile;
			profile.MappingStatus.insert({HXStr("单选框 1"), HX::CheckboxProfile{}}),
				profile.MappingStatus.insert({HXStr("单选框 2"), HX::CheckboxProfile{}}),
				profile.MappingStatus.insert({HXStr("单选框 3"), HX::CheckboxProfile{}}),
				profile.MappingStatus.insert({HXStr("单选框 4"), HX::CheckboxProfile{}}),
				HX::CheckboxGroupSingle(HXStr("单选框组，但是你只被允许选一个"), profile, true);
		} {
			static HX::CheckboxGroupProfile profile;
			profile.MappingStatus.insert({HXStr("单选框 1"), HX::CheckboxProfile{}}),
				profile.MappingStatus.insert({HXStr("单选框 2"), HX::CheckboxProfile{}}),
				profile.MappingStatus.insert({HXStr("单选框 3"), HX::CheckboxProfile{}}),
				profile.MappingStatus.insert({HXStr("单选框 4"), HX::CheckboxProfile{}}),
				HX::CheckboxGroup(HXStr("单选框组，但是你可以一次选择多个"), profile, true);
		}

		static HXGInt            count = 0;
		static HX::ButtonProfile btnProfile{};
		btnProfile.Size = {100, 60};

		HX::BeginSameLine();
		if (HX::Button(HXStr("你好！"), btnProfile)) {
			++count;
		}
		HX::Text(std::format(HXStr("你总共点了 : {} 次"), count));
		HX::EndSameLine();

		if (btnProfile.OnHold) {
			auto profile        = HX::TextProfile{};
			profile.Height      = 40;
			profile.Color       = HXColor{255, 0, 0};
			profile.Font.Style  = HXFontStyle::Black;
			profile.Font.Family = "Times New Roman";
			profile.Font.Italic = true;

			HX::Text(HXStr("English Test"), profile);
		}
		if (btnProfile.OnHover) {
			HX::Text(HXStr("你的鼠标浮在按钮上！"));
		}

		static float               speed = 1.0f;
		static HX::SliderProfile1f profile;
		static HX::SliderProfile1f profile2;
		profile.MaxValue  = 1.8f;
		profile.MinValue  = 0.2f;
		profile2.MaxValue = 1.8f;
		profile2.MinValue = 0.2f;
		HX::BeginSameLine();
		HX::Slider1f(HXStr("旋转速度"), speed, profile);
		{
			static float               testFloat[2] = {0.f, 0.f};
			static HX::SliderProfile2f multiProfile;
			multiProfile[0].MaxValue = 1.8f;
			multiProfile[0].MinValue = 0.0f;
			multiProfile[1].MaxValue = 1.8f;
			multiProfile[1].MinValue = 0.0f;
			HX::Slider2f(HXStr("Vec2 滑动选择"), testFloat, multiProfile);
		} {
			static float               testFloat[3] = {0.f, 0.f, 0.f};
			static HX::SliderProfile3f multiProfile;
			multiProfile[0].MaxValue = 1.8f;
			multiProfile[0].MinValue = 0.0f;
			multiProfile[1].MaxValue = 1.8f;
			multiProfile[1].MinValue = 0.0f;
			multiProfile[2].MaxValue = 1.8f;
			multiProfile[2].MinValue = 0.0f;
			HX::Slider3f(HXStr("Vec3 滑动选择"), testFloat, multiProfile);
		} {
			static float               testFloat[4] = {0.f, 0.f, 0.f, 0.f};
			static HX::SliderProfile4f multiProfile;
			multiProfile[0].MaxValue = 1.8f;
			multiProfile[0].MinValue = 0.0f;
			multiProfile[1].MaxValue = 1.8f;
			multiProfile[1].MinValue = 0.0f;
			multiProfile[2].MaxValue = 1.8f;
			multiProfile[2].MinValue = 0.0f;
			multiProfile[3].MaxValue = 1.8f;
			multiProfile[3].MinValue = 0.0f;
			HX::Slider4f(HXStr("Vec4 滑动选择"), testFloat, multiProfile);
		}
		HX::EndSameLine();
		{
			static int                 testInt[4] = {0, 0, 0, 0};
			static HX::SliderProfile4i multiProfile;
			multiProfile[0].MaxValue = 4;
			multiProfile[0].MinValue = 0;
			multiProfile[1].MaxValue = 4;
			multiProfile[1].MinValue = 0;
			multiProfile[2].MaxValue = 4;
			multiProfile[2].MinValue = 0;
			multiProfile[3].MaxValue = 4;
			multiProfile[3].MinValue = 0;
			HX::Slider4i(HXStr("Vec4 Int 滑动选择"), testInt, multiProfile);
		}

		HX::Canvas({400, 400}, [&Vertexes](HXBufferPainter *Painter, HXPoint Size) {
			Painter->Clear(HXColor{255, 255, 255});
			HXFont font{};
			font.Family = HXStr("Viner Hand ITC");
			Painter->DrawText(HXStr("Hello Canvas!"), font, {20, 20}, HXColor{0, 255, 0}, 38);

			std::function<std::array<float, 2>(std::array<float, 2>, std::array<float, 2>, float)> Rotate = [](
				std::array<float, 2> Point, std::array<float, 2> Origin,
				float                theta) -> std::array<float, 2> {
				float x = (Point[0] - Origin[0]) * cos(theta) - (Point[1] - Origin[1]) * sin(theta) + Origin[0];
				float y = (Point[0] - Origin[0]) * sin(theta) + (Point[1] - Origin[1]) * cos(theta) + Origin[1];

				return {x, y};
			};

			for (auto j = 0; j < 5; ++j) {
				for (auto i = 0; i < 5; ++i) {
					auto transformVert = Vertexes;
					for (auto &vertex : transformVert) {
						vertex = {vertex[0], vertex[1] + j * 1.5f};
					}
					for (auto &vertex : transformVert) {
						vertex = {vertex[0] + i * 1.5f, vertex[1]};
					}
					auto theta = (clock() / 1000.f + i) * (1.0f + (i + j)) * speed;
					for (auto &vertex : transformVert) {
						auto [x, y] = Rotate(vertex, {1.5f + i * 1.5f, 1.5f + j * 1.5f}, theta);
						vertex      = std::array<float, 2>{x, y};
					}

					HXColInt subColor = static_cast<HXColInt>((i + j) / 10.0f * 255);
					HXColor  color    = {subColor, subColor, subColor};

					Painter->DrawLine(
						{HXGInt(transformVert[0][0] * 40), HXGInt(transformVert[0][1] * 40)},
						{HXGInt(transformVert[1][0] * 40), HXGInt(transformVert[1][1] * 40)},
						color
						);
					Painter->DrawLine(
						{HXGInt(transformVert[1][0] * 40), HXGInt(transformVert[1][1] * 40)},
						{HXGInt(transformVert[2][0] * 40), HXGInt(transformVert[2][1] * 40)},
						color
						);
					Painter->DrawLine(
						{HXGInt(transformVert[2][0] * 40), HXGInt(transformVert[2][1] * 40)},
						{HXGInt(transformVert[3][0] * 40), HXGInt(transformVert[3][1] * 40)},
						color
						);
					Painter->DrawLine(
						{HXGInt(transformVert[3][0] * 40), HXGInt(transformVert[3][1] * 40)},
						{HXGInt(transformVert[0][0] * 40), HXGInt(transformVert[0][1] * 40)},
						color
						);
				}
			}
		});

		HX::EndScroller(windowScroller);

		HX::End();

		HX::Render();

		settextcolor(RGB(0, 0, 0));
		outtextxy(20, 20, std::format(HXStr("FPS : {}"), 1000.f / (clock() - start)).c_str());
		settextcolor(RGB(255, 255, 255));
		outtextxy(18, 18, std::format(HXStr("FPS : {}"), 1000.f / (clock() - start)).c_str());

		FlushBatchDraw();

		Sleep(1);
	}

	return 0;
}
